#  /**
#  * Copyright (c) 2022 Beijing Jiaotong University
#  * PhotLab is licensed under [Open Source License].
#  * You can use this software according to the terms and conditions of the [Open Source License].
#  * You may obtain a copy of [Open Source License] at: [https://open.source.license/]
#  *
#  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
#  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
#  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#  *
#  * See the [Open Source License] for more details.
#  */
#  /**
#  * Author: Zheng Wang
#  * Created: Jun. 27, 2022
#  * Supported by: National Key Research and Development Program of China
#  */
import time

import numpy as np
from phot_engine.computing_graph import PhotLabGraph


def _gen_signal_from_list(edge_list: list) -> list:
    """
            Given an edge list generate output signal list
        :param edge_list:
        :return:
        """
    output_signal_list = []
    print("edge_list length:{}".format(len(edge_list)), edge_list)
    for edge in edge_list:
        if edge.signal is not None:
            output_signal = {
                "source_vertex_id": edge.source_port.vertex_id,
                "source_port_id": edge.source_port.port_id,
                "destination_vertex_id": edge.destination_port.vertex_id,
                "destination_vertex_port_id": edge.destination_port.port_id,
                "signal": edge.signal
            }
            output_signal_list.append(output_signal)
    return output_signal_list


class SimulationTask:
    """
        a simulation task
    """

    def __init__(self, task_id, starting_executing_time, priority, graph: PhotLabGraph, global_parameter):
        self.__status = None
        self.__task_id = task_id
        self.__starting_executing_time = starting_executing_time
        self.__end_executing_time = None
        self.__priority = priority
        self.__graph = graph
        self.__global_param = global_parameter

    def set_end_executing_time(self, end_time):
        self.__end_executing_time = end_time

    def set_edge_list(self, edge_list):
        self.__graph.set_edge_list(edge_list)

    def get_start_executing_time(self):
        return self.__starting_executing_time

    def get_priority(self):
        return self.__priority

    def get_end_executing_time(self):
        return self.__end_executing_time

    def get_task_id(self):
        return self.__task_id

    def set_task_status(self, status):
        self.__status = status

    def get_task_status(self):
        return self.__status

    def get_computational_graph(self):
        return self.__graph.get_computational_graph()

    def get_global_parameter(self):
        return self.__global_param

    def get_edge_list(self) -> list:
        return self.__graph.get_edge_list()

    def get_graph(self):
        return self.__graph

    def show_computational_graph(self):
        self.__graph.show_computational_graph()

    def get_signal_by_vertex_id(self, vertex_id) -> list:
        vertex = self.__graph.get_vertex(vertex_id)
        return _gen_signal_from_list(edge_list=vertex.get_out_edge_iterator())

    def get_all_analyzer_output_signal_list(self) -> list:
        """
            Get all analyzers' output signal from a simulation task
        :return:
        """
        analyzer_vertex_list = self.__graph.get_all_analyzer_vertex()
        output_signal_list = []
        for analyzer_vertex in analyzer_vertex_list:
            output_signal_list.append(
                _gen_signal_from_list(
                    edge_list=analyzer_vertex.get_out_edge_iterator()))
        return output_signal_list

    def clear_all_signal(self):
        """
        :return:
        """
        self.__graph.clear_all_signal()

    def show_all_signal(self):
        """
            show all signals in task's edge list
        :return:
        """
        print("**********All signal in Edge**********")
        for edge in self.__graph.get_edge_list():

            print("*Edge Source port:{},Edge Destination port:{}".format(edge.source_port, edge.destination_port))
            print("*Signal: ", edge.signal)
            print("*Signal Data Type: ", type(edge.signal))
            if isinstance(edge.signal, np.ndarray):
                print("*Shape: ", edge.signal.shape)

        print("**************************************")

    def show_task_info(self):
        """
            show task info
        :return:
        """
        print("**********Simulation task information***********")
        print("*Task id:", self.__task_id)
        print("*Task execution time:", time.strftime("%Y-%m-%d %H:%M:%S",
                                                     time.localtime(int(self.__starting_executing_time))))
        print("*Task priority:", self.__priority)
        print("*Task status:", self.__status)
        if self.__end_executing_time is not None:
            print("*Task accomplished time:", time.strftime("%Y-%m-%d %H:%M:%S",
                                                            time.localtime(int(self.__end_executing_time))))
        print("************************************************")
